package com.jwds.digital.bios.business.service.service.belt.impl;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jwds.digital.bios.business.core.infrastructure.entity.basic.BasicDevice;
import com.jwds.digital.bios.business.core.infrastructure.entity.belt.BeltDayTargetHis;
import com.jwds.digital.bios.business.core.infrastructure.entity.flow.FlowBasic;
import com.jwds.digital.bios.business.core.infrastructure.mapper.basic.BasicDeviceMapper;
import com.jwds.digital.bios.business.core.infrastructure.mapper.belt.BeltPerformanceDayMapper;
import com.jwds.digital.bios.business.core.infrastructure.mapper.belt.BeltPerformanceHourMapper;
import com.jwds.digital.bios.business.core.infrastructure.mapper.belt.BeltRoutePerformanceHourMapper;
import com.jwds.digital.bios.business.core.infrastructure.mapper.flow.FlowBasicMapper;
import com.jwds.digital.bios.business.core.infrastructure.vo.belt.*;
import com.jwds.digital.bios.business.core.infrastructure.vo.feign.FlowBasicRespVO;
import com.jwds.digital.bios.business.service.service.belt.IBeltDayTargetHisService;
import com.jwds.digital.bios.business.service.service.belt.IBeltRoutePerformanceDayService;
import com.jwds.digital.bios.business.core.infrastructure.dto.belt.BeltRoutePerformanceDayReqDTO;
import com.jwds.digital.bios.business.core.infrastructure.dto.belt.assembler.BeltRoutePerformanceDayAssembler;
import com.jwds.digital.bios.business.core.infrastructure.entity.belt.BeltRoutePerformanceDay;
import com.jwds.digital.bios.business.core.infrastructure.mapper.belt.BeltRoutePerformanceDayMapper;
import com.jwds.digital.bios.business.core.exceptions.RecordNotFoundException;
import com.jwds.tdc.framework.application.lib.page.PageRequest;
import com.jwds.tdc.framework.application.lib.page.PageResponse;

import java.math.BigDecimal;
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.temporal.ChronoUnit;
import java.time.temporal.TemporalAdjusters;
import java.util.*;
import java.util.stream.Collectors;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * 线路效能天表实现类
 *
 * @author 林柏云
 * @date 2024-10-24
 */
@Slf4j
@Service
public class BeltRoutePerformanceDayServiceImpl extends ServiceImpl<BeltRoutePerformanceDayMapper, BeltRoutePerformanceDay> implements IBeltRoutePerformanceDayService {

    @Autowired
    private BeltRoutePerformanceDayMapper baseMapper;
    @Autowired
    private IBeltDayTargetHisService beltDayTargetHisService;
    @Override
    public BeltRoutePerformanceDayRespVO queryById(Long id) {
        if (id == null) {
            return null;
        }
        BeltRoutePerformanceDay entity = baseMapper.selectById(id);
        return BeltRoutePerformanceDayAssembler.entity2dto(entity);
    }

    @Override
    public PageResponse<BeltRoutePerformanceDayRespVO> page(PageRequest<BeltRoutePerformanceDayReqDTO> request) {
        BeltRoutePerformanceDayReqDTO condition = request.getQueryCondition();
        Page<BeltRoutePerformanceDayRespVO> page = new Page<>(request.getPageIndex(), request.getPageSize());
        IPage<BeltRoutePerformanceDayRespVO> pageData = baseMapper.pageQuery(page, condition);
        return new PageResponse<>((Page<?>) pageData, pageData.getRecords());
    }

    @Override
    public List<BeltRoutePerformanceDayRespVO> list(BeltRoutePerformanceDayReqDTO reqDto) {
        return baseMapper.queryList(reqDto);
    }

    @Override
    public void add(BeltRoutePerformanceDayReqDTO reqDto) {
        BeltRoutePerformanceDay entity = BeltRoutePerformanceDayAssembler.dto2entity(reqDto);
        baseMapper.insert(entity);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void batchAdd(List<BeltRoutePerformanceDayReqDTO> dtoList) {
        dtoList.forEach(this::add);
    }

    @Override
    public void update(BeltRoutePerformanceDayReqDTO reqDto) {
        BeltRoutePerformanceDay oldEntity = baseMapper.selectById(reqDto.getId());
        if (oldEntity == null) {
            throw new RecordNotFoundException();
        }
        BeltRoutePerformanceDay newEntity = BeltRoutePerformanceDayAssembler.dto2entity(reqDto, oldEntity);
        baseMapper.updateById(newEntity);
    }

    @Override
    public void delete(Long id) {
        BeltRoutePerformanceDay oldEntity = baseMapper.selectById(id);
        if (oldEntity == null) {
            throw new RecordNotFoundException();
        }
        baseMapper.deleteById(id);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void batchDelete(List<Long> ids) {
        for (Long id : ids) {
            delete(id);
        }
    }
    @Autowired
    private BeltRoutePerformanceHourMapper beltRoutePerformanceHourMapper;
    @Override
    public BeltRoutePerformanceDayRespVO BeltRoutePerformanceDayRespVO(Long routeId) {
        // 线路效能天基本信息
        //BeltRoutePerformanceDayRespVO lineEfficiencyHour = baseMapper.BeltRoutePerformanceDayRespVO(routeId, 1);
        BeltRoutePerformanceDayRespVO lineEfficiencyDay = baseMapper.BeltRoutePerformanceDayRespVO(routeId, 1);

        if (lineEfficiencyDay == null) {
            return null;
        }

        // 计算启动空转时间
        BigDecimal startIdleTime = BigDecimal.valueOf(ChronoUnit.DAYS.between(lineEfficiencyDay.getStartTime(), lineEfficiencyDay.getEndTime()));
        lineEfficiencyDay.setStartIdleTimeInOperation(startIdleTime);


        // 计算停止空转时间
        BigDecimal endIdleTime = BigDecimal.valueOf(ChronoUnit.DAYS.between(lineEfficiencyDay.getStartEmptyTime(), lineEfficiencyDay.getEndEmptyTime()));
        lineEfficiencyDay.setEndIdleTimeInOperation(endIdleTime);

        // 计算运行中空载时间
        lineEfficiencyDay.setIdleTimeInOperation(lineEfficiencyDay.getNoLoadRuntime().subtract(startIdleTime).subtract(endIdleTime));

        // 计算启动空转时间占比
        lineEfficiencyDay.setStartIdleTimeConsumptionRatio(startIdleTime.divide(lineEfficiencyDay.getNoLoadRuntime(), 2, BigDecimal.ROUND_HALF_UP).multiply(BigDecimal.valueOf(100)));

        // 计算停止空转时间占比
        lineEfficiencyDay.setEndIdleTimeConsumptionRatio(endIdleTime.divide(lineEfficiencyDay.getNoLoadRuntime(), 2, BigDecimal.ROUND_HALF_UP).multiply(BigDecimal.valueOf(100)));

        // 计算运行中空载时间占比
        lineEfficiencyDay.setInOperationIdleTImeConsumptionRatio(lineEfficiencyDay.getIdleTimeInOperation().divide(lineEfficiencyDay.getNoLoadRuntime(), 2, BigDecimal.ROUND_HALF_UP).multiply(BigDecimal.valueOf(100)));

        // 计算运行中空载能耗
        lineEfficiencyDay.setIdleEnergyInOperation(lineEfficiencyDay.getNoLoadPowerConsumption().subtract(lineEfficiencyDay.getStartNoLoadPowerConsumption()).subtract(lineEfficiencyDay.getEndNoLoadPowerConsumption()));

        // 计算运行中空载能耗占比
        lineEfficiencyDay.setInOperationIdleEnergyConsumptionRatio(lineEfficiencyDay.getIdleEnergyInOperation().divide(lineEfficiencyDay.getNoLoadPowerConsumption(),2, BigDecimal.ROUND_HALF_UP));

        // 计算启动空载能耗占比
        lineEfficiencyDay.setStartIdleTimeConsumptionRatio(lineEfficiencyDay.getStartNoLoadPowerConsumption().divide(lineEfficiencyDay.getNoLoadPowerConsumption(),2, BigDecimal.ROUND_HALF_UP));

        // 计算停止空载能耗占比
        lineEfficiencyDay.setEndIdleTimeConsumptionRatio(lineEfficiencyDay.getEndNoLoadPowerConsumption().divide(lineEfficiencyDay.getNoLoadPowerConsumption(),2, BigDecimal.ROUND_HALF_UP));
        // 获取今天的日期
        //LocalDate today = LocalDate.now();
/*// 昨天的开始时间
        LocalDateTime startTime = LocalDate.now().minusDays(1).atStartOfDay();
// 昨天的结束时间
        LocalDateTime endTime = LocalDate.now().minusDays(1).atTime(LocalTime.MAX);*/

        /*// 今天的开始时间
        LocalDateTime startTime = today.atStartOfDay();
        // 今天的结束时间
        LocalDateTime endTime = today.atTime(LocalTime.MAX);*/

        // 获取本周的开始日期（星期一）
        LocalDateTime startTime = LocalDate.now().with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY)).atStartOfDay();
        // 获取本周的结束日期（星期日）
        LocalDateTime endTime = LocalDate.now().with(TemporalAdjusters.nextOrSame(DayOfWeek.SUNDAY)).atStartOfDay();


        //合格线
        BeltDayTargetHis beltDayTargetHis = beltDayTargetHisService.selectLatest();
        lineEfficiencyDay.setQualifiedLine(beltDayTargetHis.getWorkEfficiency());
        //平均电机运行效率==------------------------------------
        lineEfficiencyDay.setOperationEfficiency(lineEfficiencyDay.getOperationEfficiency());

        List<AverageMotorOperatingEfficiencyStats> averageMotorOperatingEfficiencyList =beltRoutePerformanceHourMapper.getAverageMotorOperatingEfficiencyStats(routeId);
        if (averageMotorOperatingEfficiencyList == null) {
            return null;
        }
        lineEfficiencyDay.setAverageMotorOperatingEfficiencyStats(averageMotorOperatingEfficiencyList);

        // 负载率,空负载率,作业效率
        List<BeltRoutePerformanceDayRespVO> day = baseMapper.getLineEfficiencyDayS(routeId, startTime, endTime);
        List<LoadRateAndWorkingEfficiency> loadRateAndWorkingEfficiencies = day.stream().map(h -> {
            LoadRateAndWorkingEfficiency loadRateAndWorkingEfficiency = new LoadRateAndWorkingEfficiency();
            loadRateAndWorkingEfficiency.setWorkEfficiency(h.getWorkEfficiency());
            loadRateAndWorkingEfficiency.setAvgNoLoadRate(h.getAvgNoLoadRate());
            loadRateAndWorkingEfficiency.setAvgLoadRate(h.getAvgLoadRate());
            loadRateAndWorkingEfficiency.setBelongDate(h.getBelongDate());
            return loadRateAndWorkingEfficiency;
        }).collect(Collectors.toList());
        lineEfficiencyDay.setLoadRateAndWorkingEfficiencyList(loadRateAndWorkingEfficiencies);

        return lineEfficiencyDay;
    }
    @Autowired
    private BasicDeviceMapper basicDeviceMapper;
    @Autowired
    private FlowBasicMapper flowBasicMapper;

    @Autowired
    private BeltPerformanceDayMapper beltPerformancedMapper;
    @Autowired
    private BeltRoutePerformanceDayMapper beltRoutePerformanceDayMapper;
    @Override
    public List<Map<String, Object>> getBeltInfoById(Long id) {
        // 根据 ID 查询 flow_basic 表
        FlowBasicRespVO flowBasic = flowBasicMapper.searchById(id);
        if (flowBasic == null) {
            return null;
        }

        // 将 flow_name 按下划线 _ 分割
        String flowName = flowBasic.getFlowName();
        List<String> beltNames = Arrays.asList(flowName.split("-"));

        // 根据 beltName 查询 basic_device 表
        List<BasicDevice> devices = basicDeviceMapper.selectByDeviceNames(beltNames);
        if (devices == null) {
            return null;
        }
        // 获取所有皮带的 ID
        List<Integer> beltIds = devices.stream()
                .map(BasicDevice::getId)
                .collect(Collectors.toList());

        // 统计所有皮带的总长度
        BigDecimal totalBeltLength = flowBasic.getFlowDistance();
        /*double totalBeltLength = devices.stream()
                .filter(device -> device != null && device.getDeviceLength() != null)
                .mapToDouble(device -> device.getDeviceLength().doubleValue())
                .sum();*/

        // 根据 beltId 查询 belt_performance_hour 表
        List<BeltPerformanceDayRespVO> performances = beltPerformancedMapper.selectByBeltIds(beltIds);
        if (performances == null) {
            return null;
        }
        // 计算每条皮带的运输效率和运输能耗
        Map<Integer, BasicDevice> deviceMap = devices.stream()
                .collect(Collectors.toMap(BasicDevice::getId, device -> device));

        List<Map<String, Object>> result = performances.stream().map(performance -> {
            BasicDevice device = deviceMap.get(performance.getBeltId().intValue());
            if (device == null) {
                // 返回一个空的 Map 或者跳过当前项
                return new HashMap<String, Object>(); // 返回一个空的 Map
            }
            BigDecimal totalTransport = performance.getTotalTransport() == null ? BigDecimal.ZERO : performance.getTotalTransport();
            BigDecimal allRuntime = performance.getLoadRuntime() == null ? BigDecimal.ZERO : performance.getLoadRuntime();
            BigDecimal totalPowerConsumption = performance.getTotalPowerConsumption() == null ? BigDecimal.ZERO : performance.getTotalPowerConsumption();
            // 检查 totalTransport 和 allRuntime 是否为 null
            if (totalTransport == null || allRuntime == null) {
                log.error("totalTransport or allRuntime is null for beltId: {}", performance.getId());
                return null;
            }
            BigDecimal transportEfficiency = allRuntime.compareTo(BigDecimal.ZERO) == 0 ? BigDecimal.ZERO : totalTransport.divide(allRuntime, 4, BigDecimal.ROUND_HALF_UP);
            BigDecimal transportEnergyConsumption = totalTransport.compareTo(BigDecimal.ZERO) == 0 ? BigDecimal.ZERO : totalPowerConsumption.divide(totalTransport, 4, BigDecimal.ROUND_HALF_UP);

            return new HashMap<String, Object>() {{
                put("beltName", device.getDeviceName());
                put("beltLength", device.getDeviceLength());
                put("transportEfficiency", transportEfficiency);
                put("transportEnergyConsumption", transportEnergyConsumption);
            }};
        }).collect(Collectors.toList());

        // 获取整条线路的性能记录
        BeltRoutePerformanceDayRespVO respVO = beltRoutePerformanceDayMapper.searchByRouteId(id);
        if (respVO == null) {
            return null;
        }
        BigDecimal totalRouteTransport = respVO.getTotalTransport();
        BigDecimal totalRouteRuntime = respVO.getAllRuntime();
        BigDecimal totalRoutePowerConsumption = respVO.getTotalPowerConsumption();
        // 检查 totalRouteTransport 和 totalRouteRuntime 是否为 null
        if (totalRouteTransport == null || totalRouteRuntime == null) {
            log.error("totalRouteTransport or totalRouteRuntime is null for id: {}", id);
            return null;
        }
        BigDecimal routeTransportEfficiency = totalRouteRuntime.compareTo(BigDecimal.ZERO) == 0 ? BigDecimal.ZERO : totalRouteTransport.divide(totalRouteRuntime, 4, BigDecimal.ROUND_HALF_UP);
        BigDecimal routeTransportEnergyConsumption = totalRouteTransport.compareTo(BigDecimal.ZERO) == 0 ? BigDecimal.ZERO : totalRoutePowerConsumption.divide(totalRouteTransport, 4, BigDecimal.ROUND_HALF_UP);

        // 将总长度、整条线路的运输效率和运输能耗以及线路名称添加到结果中
        Map<String, Object> summary = new HashMap<>();
        summary.put("totalBeltLength", totalBeltLength);
        summary.put("routeTransportEfficiency", routeTransportEfficiency);
        summary.put("routeTransportEnergyConsumption", routeTransportEnergyConsumption);
        summary.put("flowName", flowName); // 添加整条线路的名称
        result.add(summary);

        return result;
    }

}
